home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C ++ / Frameworks / MacZoop 1.6.5 / Basic Classes / Z Sources / ZEventHandler.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-07  |  19.2 KB  |  750 lines  |  [TEXT/CWIE]

  1. /*************************************************************************************************
  2. *
  3. *
  4. *            ObjectMacZapp            -- a standard Mac OOP application template
  5. *
  6. *
  7. *
  8. *            ZEventHandler.cpp        -- the event handler object
  9. *
  10. *
  11. *
  12. *
  13. *
  14. *            © 1996, Graham Cox
  15. *
  16. *
  17. *
  18. *
  19. *************************************************************************************************/
  20.  
  21. #include    "ZEventHandler.h"
  22. #include    "MacZoop.h"
  23. #include    "ZWindow.h"
  24. #include    "ZCommander.h"
  25. #include    "ZDialog.h"
  26.  
  27. #include    <LowMem.h>
  28.  
  29. // gSleep is the sleep period passed to WaitNextEvent
  30.  
  31. short            gSleep = kFrontSleep;
  32.  
  33. // gCurHandler is the current ZCommander object that wants to handle commands. This will
  34. // usually be the active window or the application
  35.  
  36. ZCommander*        gCurHandler = NULL;
  37.  
  38. // prototype of handler function for apple-events- sends them up the command chain.
  39.  
  40. static pascal OSErr        ZAEHandler ( AppleEvent* aeEvt, AppleEvent* reply, long refCon );
  41.  
  42. // global UPP to same
  43.  
  44. AEEventHandlerUPP        gAEUPP  = NewAEEventHandlerProc( ZAEHandler );
  45.  
  46.  
  47. /*-------------------------------***  CONSTRUCTOR  ***---------------------------------*/
  48.  
  49. ZEventHandler::ZEventHandler()
  50. {
  51.     clicks = 0;
  52.     inBackground = FALSE;
  53.     
  54.     gCurHandler = gApplication;
  55. }
  56.  
  57.  
  58. /*---------------------------------***  GETANEVENT  ***---------------------------------*/
  59. /*    
  60.  
  61. gets the next event off the queue. If it's a null event, give idle time
  62.  
  63. ----------------------------------------------------------------------------------------*/
  64.  
  65. void    ZEventHandler::GetAnEvent( const short mask )
  66. {
  67.     // gets an event from the event queue and sets "theEvent" to it.
  68.     
  69.     if (! WaitNextEvent( mask, &theEvent, gSleep, NULL ))
  70.         PassIdle();
  71.         
  72.     // dispatch the cursor to the current window, so it's shape can be set. If the cursor is animating,
  73.     // we assume that it was set on purpose for a lengthy operation, so we do not dispatch the cursor
  74.     // in this case. The animating cursor will be cancelled when the application gets a null event.
  75.     
  76.     if (! CursorAnimating())
  77.     {
  78.         ZWindow*    aZW = gWindowManager->LocateWindow( theEvent.where );
  79.         WindowPtr    w = NULL;
  80.         
  81.         if ( aZW )
  82.             w = aZW->GetMacWindow();
  83.         
  84.         if ( w )
  85.         {
  86.             // check to see that the window is not "windowshaded"- if
  87.             // it is, don't dispatch the cursor. If the window is shaded,
  88.             // its contRgn will be empty.
  89.             
  90.             if (! EmptyRgn( ((WindowPeek) w)->contRgn ))
  91.             {
  92.                 if ( aZW )
  93.                 {
  94.                     Point        mouse;
  95.                     GrafPtr        savePort;
  96.                     
  97.                     mouse = theEvent.where;
  98.                     
  99.                     GetPort( &savePort );
  100.                     SetPort( w );
  101.                     
  102.                     GlobalToLocal( &mouse );
  103.                     SetPort( savePort );
  104.                     
  105.                     // if the point is inside the window, dispatch to the window,
  106.                     // otherwise reset the cursor to an arrow. If the window is not the top
  107.                     // window, the cursor is not dispatched, but reset, unless the window is
  108.                     // a floater, in which case we do dispatch it if there not a modal dialog
  109.                     // in front of it. The result is correct for what the user expects.
  110.                     
  111.                     if     ( PtInRect( mouse, &w->portRect ) &&
  112.                         ( aZW == gApplication->GetFrontWindow() ||
  113.                         ( aZW->Floats() && ! gWindowManager->IsDialog( gApplication->GetFrontWindow()))))
  114.                         aZW->AdjustCursor( mouse, theEvent.modifiers );
  115.                     else
  116.                         SetCursor( &qd.arrow );
  117.                 }
  118.             }
  119.             else
  120.                 SetCursor( &qd.arrow );
  121.         }
  122.         else
  123.             SetCursor( &qd.arrow );
  124.     }
  125. }
  126.  
  127.  
  128. /*-----------------------------***  DISPATCHANEVENT  ***--------------------------------*/
  129. /*    
  130.  
  131. determine what sort of event it is and call the relevant handler method.
  132.  
  133. ----------------------------------------------------------------------------------------*/
  134.  
  135. void    ZEventHandler::DispatchAnEvent()
  136. {
  137.     // dispatches the event according to its type, etc
  138.     
  139.     Boolean        isAutoKey = FALSE;
  140.     char         theKey;
  141.             
  142.     // see if this is a dialog event and process it. Note that for floaters to work, we can't use
  143.     // IsDialogEvent, since it assumes FrontWindow() returns the active document- with floaters, 
  144.     // this is not true, so we have to ask our own wMgr object to check for us.
  145.  
  146.     if ( gWindowManager->CheckDialogEvent( &theEvent ))
  147.     {
  148.         // allow the event to be modified before the dialog processes it.
  149.         if ( PrefilterDialogEvent())
  150.             return;    // event was fully handled
  151.     }
  152.  
  153.     switch ( theEvent.what )
  154.     {
  155.         case mouseDown:
  156.             HandleMouseEvent( theEvent );
  157.             break;
  158.         case activateEvt:
  159.             
  160.             // following defined in ZWindowManager.h
  161.             
  162.             #ifdef _ACTIVATE_EVENTS_ARE_REAL
  163.             HandleWindowActivate(    (WindowPtr) theEvent.message,
  164.                                     (theEvent.modifiers & activeFlag) );
  165.             #endif
  166.             break;
  167.         case autoKey:
  168.             isAutoKey = TRUE;
  169.         case keyDown:
  170.             theKey = theEvent.message & charCodeMask;
  171.             
  172.             HandleKeyEvent( theKey, isAutoKey );
  173.             break;
  174.         case updateEvt:
  175.             HandleWindowUpdate((WindowPtr) theEvent.message );
  176.             break;
  177.         case diskEvt:
  178.         {
  179.             Point dPt = {100,100};
  180.             
  181.             if( HiWord( theEvent.message ) != 0)
  182.                 DIBadMount( dPt, theEvent.message );
  183.             break;
  184.         }
  185.         case kHighLevelEvent:
  186.             HandleHLEvent( theEvent );
  187.             break;
  188.         case osEvt:
  189.             HandleOSEvent( theEvent );
  190.             break;
  191.     }
  192. }
  193.  
  194.  
  195. /*------------------------------***  HANDLEKEYEVENT  ***--------------------------------*/
  196. /*    
  197.  
  198. process keystrokes. Command-Key sequences are passed to the menu handler
  199. ----------------------------------------------------------------------------------------*/
  200.  
  201. void    ZEventHandler::HandleKeyEvent( const char theKey, const Boolean isAutoKey )
  202. {
  203.     long mSelect;
  204.     
  205.     if ( theEvent.modifiers & cmdKey )
  206.     {
  207.         // if this is a command-key combination, translate this to a
  208.         // menu command as if it were picked from the menu.
  209.         
  210.         if (! isAutoKey)
  211.         {
  212.             gMenuBar->DimMenus();
  213.             
  214.             // ask the command chain to reenable the relevant menu items
  215.             
  216.             if ( gCurHandler )
  217.                 gCurHandler->UpdateMenus();
  218.             
  219.             mSelect = MenuKey( theKey );
  220.             
  221.             gMenuBar->DispatchCommand( mSelect );        
  222.         }    
  223.         return;
  224.     }
  225.  
  226.     // the user is typing- send the characters to the current commander
  227.     
  228.     if( gCurHandler )
  229.         gCurHandler->Type( theKey );
  230. }
  231.  
  232.  
  233.  
  234.  
  235. /*---------------------------***  PROCESSDIALOGEVENT  ***-------------------------------*/
  236. /*    
  237.  
  238. a modeless dialog is up and the user clicked one of its enabled items. Override this to
  239. process it for the dialog. This passes clicks for ZDialogs to its ClickItem method
  240.  
  241. ----------------------------------------------------------------------------------------*/
  242.  
  243. void    ZEventHandler::ProcessDialogEvent( const DialogPtr theDialog, const short itemHit )
  244. {
  245.     // if this is a ZDialog object, call it's ClickItem method
  246.     
  247.     ZDialog*    aZD = (ZDialog*) GetWRefCon( theDialog );
  248.     
  249.     if( aZD )
  250.         aZD->ClickItem( itemHit );
  251. }
  252.  
  253.  
  254.  
  255. /*-------------------------***  PREFILTERDIALOGEVENT  ***-------------------------------*/
  256. /*    
  257.  
  258. opportunity to prefilter the event for a dialog before the dialog manager gets it. This
  259. determines which dialog object to call, and calls its filter function. This is how
  260. return and enter keys, etc, are processed.
  261.  
  262. ----------------------------------------------------------------------------------------*/
  263.  
  264. Boolean    ZEventHandler::PrefilterDialogEvent()
  265. {
  266.     Boolean        handled = FALSE;
  267.     
  268.     ZDialog*    zDW = dynamic_cast<ZDialog*> ( gApplication->GetFrontWindow());
  269.     
  270.     if ( zDW )
  271.         handled = zDW->Filter( &theEvent );
  272.  
  273.     return handled;
  274. }
  275.  
  276.  
  277. /*-------------------------------***  COUNTCLICKS  ***----------------------------------*/
  278. /*    
  279.  
  280. count up the number of rapid mouse-clicks to detect double-clicks, etc.
  281.  
  282. ----------------------------------------------------------------------------------------*/
  283.  
  284. void    ZEventHandler::CountClicks( const WindowPtr target, const long clickTicks, const Point globalMouse )
  285. {
  286.     static    WindowPtr     prevTarget = NULL;
  287.     static    long        lastClickTicks = 0;
  288.     static    Point        lastClick = {0,0};
  289.     
  290.     GrafPtr    savePort;
  291.     Point    gMouse;
  292.     
  293.     gMouse = globalMouse;
  294.     
  295.     GetPort( &savePort );
  296.     SetPort( target );
  297.     GlobalToLocal( &gMouse );
  298.     
  299.     if (target == prevTarget)
  300.     {
  301.         // the target window is the same as the last click, is the click
  302.         // within the double-click period set by the user?
  303.         
  304.         if ( clickTicks < lastClickTicks + GetDblTime())
  305.         {
  306.             // yes, the click is in time. Finally, we ask the window
  307.             // whether we should consider the click as being in the same place.    
  308.             
  309.             ZWindow*    zW = GetZWindow( target );
  310.             
  311.             if ( zW && zW->ClickInSamePlace( lastClick, gMouse ))
  312.                 clicks++;
  313.             else
  314.                 clicks = 1;
  315.         }
  316.         else
  317.             clicks = 1;
  318.     }
  319.     else
  320.         clicks = 1;
  321.     
  322.     // store the click point, target and click time for the next time
  323.             
  324.     lastClick = gMouse;
  325.     prevTarget = target;
  326.     lastClickTicks = clickTicks;
  327.  
  328.     SetPort( savePort );
  329. }
  330.  
  331.  
  332. /*---------------------------***  HANDLEMOUSEEVENT  ***---------------------------------*/
  333. /*    
  334.  
  335. handle mouse button clicks. This finds the target window or other part of the screen
  336.  
  337. ----------------------------------------------------------------------------------------*/
  338.  
  339. void    ZEventHandler::HandleMouseEvent( const EventRecord& theEvent)
  340. {
  341.     WindowPtr        targetWindow;
  342.     short            partCode;
  343.     long            mSelect;
  344.     Point            mousePt;
  345.     ZWindow*        zappWindow;
  346.     
  347.     // find out what part of the screen the mouse was clicked on
  348.     
  349.     partCode = FindWindow( theEvent.where, &targetWindow );
  350.     
  351.     // if it was any sort of window, get the ZWindow object associated with it, if any.
  352.     
  353.     if ( targetWindow )
  354.         zappWindow = GetZWindow( targetWindow );
  355.     
  356.     switch (partCode)
  357.     {    
  358.         case inDesk:
  359.             break;
  360.         
  361.         case inMenuBar:
  362.             // the user clicked the menubar.
  363.  
  364.             gMenuBar->ClickMenuBar( theEvent.where );
  365.             
  366.             break;
  367.         
  368.         case inSysWindow:
  369.             SystemClick( &theEvent, targetWindow );    // system will handle it (DA window)
  370.             break;
  371.         
  372.         case inContent:
  373.             if ( targetWindow )                        // the user clicked in a window
  374.             {
  375.                 // if there's a modal dialog up, clicks in other windows result in a beep.
  376.                 
  377.                 ZDialog*    aZD = dynamic_cast<ZDialog*> ( gApplication->GetFrontWindow());
  378.                 Boolean        dialogUp = ( aZD && aZD->IsModal());
  379.                 
  380.                 CountClicks( targetWindow, theEvent.when, theEvent.where );    // double click?
  381.                 
  382.                 // if the window is top window or top floater, pass the click to the window.
  383.                 
  384.                 if( zappWindow &&
  385.                     (zappWindow == gApplication->GetFrontWindow() ||
  386.                     (zappWindow == gWindowManager->GetTopFloater() && ! dialogUp )))
  387.                 {
  388.                     // if the window is already active, pass the click to the window object
  389.                     // in its local coordinate system.
  390.                     
  391.                     mousePt = theEvent.where;
  392.                     
  393.                     zappWindow->Focus();
  394.                     GlobalToLocal( &mousePt );
  395.                     zappWindow->Click( mousePt, theEvent.modifiers );    
  396.                 }
  397.                 else
  398.                 {
  399.                     // if the window wasn't active, make it active. If there is a modal dialog in
  400.                     // front, then this action is not permitted.
  401.                     
  402.                     if ( dialogUp )
  403.                     {
  404.                         SysBeep( 1 );
  405.                         break;
  406.                     }
  407.                     // otherwise, process the click    
  408.  
  409.                     if ( zappWindow )
  410.                     {
  411.                         // make this window the active one
  412.                         
  413.                         zappWindow->Select();
  414.                         
  415.                         // if the window is a floater, ask it to process the click as well- 
  416.                         // floaters process "front" clicks even when they were not initially
  417.                         // active, since floaters are all 'peers' of one another.
  418.                     
  419.                         if ( zappWindow->Floats())
  420.                         {
  421.                             mousePt = theEvent.where;
  422.                             
  423.                             zappWindow->Focus();
  424.                             GlobalToLocal( &mousePt );
  425.                             zappWindow->Click( mousePt, theEvent.modifiers );
  426.                         }
  427.                     }
  428.                 }
  429.             }
  430.             break;
  431.         
  432.         case inDrag:
  433.         {
  434.             // the user wants to drag the window. Only permit this if no
  435.             // modal dialog is in front of it, or the command key is down.
  436.             
  437.             ZDialog*    aZD = (ZDialog*) gApplication->GetFrontWindow();
  438.             
  439.             if ((((WindowPeek) aZD->GetMacWindow())->windowKind == dialogKind) &&
  440.                 aZD->IsModal() &&
  441.                 (targetWindow != aZD->GetMacWindow()) &&
  442.                 ! (theEvent.modifiers & cmdKey))
  443.                 break;
  444.             
  445.             ZWindow*    zw = GetZWindow( targetWindow );
  446.             gWindowManager->DragWindowOutline( zw, theEvent.where, theEvent.modifiers );
  447.             
  448.             break;
  449.         }
  450.         
  451.         case inGrow:
  452.         {
  453.             // the user wants to resize the window
  454.             
  455.             Rect szRect;
  456.             
  457.             if ( zappWindow )
  458.             {
  459.                 zappWindow->GetSizeRect( &szRect );
  460.                 
  461.                 szRect.right++;
  462.                 szRect.bottom++;
  463.                 
  464.                 mSelect = GrowWindow( targetWindow, theEvent.where, &szRect );
  465.             
  466.                 if ( mSelect )
  467.                 {
  468.                     // if the command key was down, then we are attempting to override the
  469.                     // current settings for sizerect. Thus we need to change the size rect
  470.                     // to the desired size first:
  471.                     
  472.                     if ( theEvent.modifiers & cmdKey )
  473.                     {
  474.                         szRect.right = MAX( LoWord( mSelect ), szRect.right - 1 );
  475.                         szRect.bottom = MAX( HiWord( mSelect ), szRect.bottom - 1 );
  476.                         
  477.                         zappWindow->SetSizeRect( szRect );
  478.                     }
  479.                     
  480.                     zappWindow->SetSize( LoWord( mSelect ), HiWord( mSelect ));
  481.                 }
  482.             }
  483.             break;
  484.         }
  485.         
  486.         case inGoAway:
  487.             if ( TrackGoAway( targetWindow, theEvent.where ))
  488.             {
  489.                 // if the user clicks in the go-away box, the window will be closed. If the
  490.                 // option key is down, we close all of the windows.
  491.                 
  492.                 if ( theEvent.modifiers & optionKey )
  493.                     gApplication->CloseAll( zappWindow->Floats());
  494.                 else
  495.                 {
  496.                     if ( zappWindow )
  497.                         zappWindow->Close( gApplication->GetPhase());
  498.                 }
  499.             }
  500.             break;
  501.         
  502.         case inZoomIn:
  503.         case inZoomOut:
  504.             if( TrackBox( targetWindow, theEvent.where, partCode ))
  505.             {
  506.                 // if the user clicked in the zoom box, the window will be zoomed
  507.                 
  508.                 if( zappWindow )
  509.                     zappWindow->Zoom( partCode );
  510.             }
  511.             break;
  512.     }
  513. }
  514.  
  515.  
  516. /*---------------------------***  HANDLEWINDOWUPDATE  ***-------------------------------*/
  517. /*    
  518.  
  519. to handle an update event, focus the window and ask it do draw its contents.
  520.  
  521. ----------------------------------------------------------------------------------------*/
  522.  
  523. void    ZEventHandler::HandleWindowUpdate( const WindowPtr theWindow )
  524. {
  525.     ZWindow*        zappWindow = NULL;
  526.     GrafPtr            savePort;
  527.     Boolean            memState;
  528.     
  529.     if ( theWindow )
  530.         zappWindow = GetZWindow( theWindow );
  531.     
  532.     if ( zappWindow )
  533.     {
  534.         memState = gApplication->memIsShort;
  535.         
  536.         GetPort( &savePort );
  537.         zappWindow->Focus();
  538.         
  539.         BeginUpdate( theWindow );
  540.         
  541.         try
  542.         {
  543.             zappWindow->Draw();
  544.         }
  545.         catch( OSErr err )
  546.         {
  547.             EndUpdate( theWindow );
  548.             SetPort( savePort );
  549.             
  550.             throw err;
  551.         }
  552.         
  553.         EndUpdate( theWindow );
  554.         
  555.         // if the draw resulted in a memory shortage, suppress the warning, since
  556.         // that will trigger further updates, etc.
  557.         
  558.         if ( gApplication->memIsShort != memState )
  559.             gApplication->userHasSeenAlert = TRUE;
  560.             
  561.         SetPort(savePort);    
  562.     }
  563. }
  564.  
  565.  
  566.  
  567. /*---------------------------------***  PASSIDLE  ***-----------------------------------*/
  568. /*    
  569.  
  570. send the idle command to the current handler, and pass it up the chain
  571.  
  572. ----------------------------------------------------------------------------------------*/
  573.  
  574.  
  575. void    ZEventHandler::PassIdle()
  576. {
  577.     // called repeatedly for null events. This passes idle messages to the current commander
  578.     
  579.     if ( gCurHandler )
  580.         gCurHandler->Idle();
  581.         
  582.     // floaters may want idle time too, though they are not part of the command chain. We
  583.     // ask the window manager to give them time:
  584.     
  585.     gWindowManager->FloatIdle();
  586. }
  587.  
  588.  
  589.  
  590. /*--------------------------***  HANDLEWINDOWACTIVATE  ***------------------------------*/
  591. /*    
  592.  
  593. calls activate/deactivate for window, and sets up the current handler
  594.  
  595. ----------------------------------------------------------------------------------------*/
  596.  
  597. void    ZEventHandler::HandleWindowActivate( const WindowPtr theWindow, const Boolean state )
  598. {
  599.     // handles the activate and deactivate events. This calls the window object with
  600.     // the activate messages, and also sets up gCurHandler.
  601.  
  602.     ZWindow*        zappWindow = NULL;
  603.     
  604.     if ( theWindow )
  605.         zappWindow = GetZWindow( theWindow );
  606.     
  607.     if ( zappWindow )
  608.     {
  609.         if ( state )
  610.         {
  611.             zappWindow->Focus();
  612.             zappWindow->Activate();
  613.             gCurHandler = zappWindow->GetHandler();
  614.         }
  615.         else
  616.         {
  617.             zappWindow->Focus();
  618.             zappWindow->Deactivate();
  619.             gCurHandler = zappWindow->GetBoss();
  620.         }
  621.     }
  622. }
  623.  
  624.  
  625. /*------------------------------***  HANDLEOSEVENT  ***---------------------------------*/
  626. /*    
  627.  
  628. handle the suspend and resume events sent by MultiFinder/System 7
  629.  
  630. ----------------------------------------------------------------------------------------*/
  631.  
  632. void    ZEventHandler::HandleOSEvent( const EventRecord& theEvent )
  633. {
  634.     if ( theEvent.message & suspendResumeMessage )
  635.     {
  636.         inBackground = FALSE;
  637.         gSleep = kFrontSleep;
  638.         gWindowManager->Resume();    
  639.         gClipboard->ConvertToPrivate();
  640.     }
  641.     else
  642.     {
  643.         inBackground = TRUE;
  644.         gSleep = kBackSleep;
  645.         gClipboard->ConvertFromPrivate();
  646.         gWindowManager->Suspend();    
  647.     }
  648. }
  649.  
  650.  
  651. /*------------------------------***  HANDLEHLEVENT  ***---------------------------------*/
  652. /*    
  653.  
  654. handle the high level events sent by AOCE, Applescript, et al.
  655.  
  656. ----------------------------------------------------------------------------------------*/
  657.  
  658. void    ZEventHandler::HandleHLEvent( const EventRecord& theEvent)
  659. {
  660.     // handles high level events such as applescript events, etc.
  661.     
  662.     if ( theEvent.message == typeAppleEvent )
  663.         FailOSErr( AEProcessAppleEvent( &theEvent ));
  664.     else
  665.         gApplication->ProcessHLEvent( theEvent );
  666. }
  667.  
  668.  
  669. /*-----------------------***  INSTALLAPPLESCRIPTHANDLERS  ***---------------------------*/
  670. /*    
  671.  
  672. install the handler vectors needed to field applescript events. BY default this installs
  673. the four required events. You can override this to install more, or call the method
  674. below as needed.
  675. ----------------------------------------------------------------------------------------*/
  676.  
  677. void    ZEventHandler::InstallApplescriptHandlers()
  678. {
  679.     InstallAppleEventHandler( kCoreEventClass, kAEOpenApplication );
  680.     InstallAppleEventHandler( kCoreEventClass, kAEOpenDocuments );
  681.     InstallAppleEventHandler( kCoreEventClass, kAEPrintDocuments );
  682.     InstallAppleEventHandler( kCoreEventClass, kAEQuitApplication );
  683. }
  684.  
  685.  
  686. /*------------------------***  INSTALLAPPLEEVENTHANDLER  ***----------------------------*/
  687. /*    
  688.  
  689. install the handler vector needed to field all applescript events. Call this once for
  690. each event class and ID you wish to process. Apple Events will be unpacked by the global
  691. vector proc and sent up the command chain. You can intercept them there and process them
  692. as needed.
  693. ----------------------------------------------------------------------------------------*/
  694.  
  695. void    ZEventHandler::InstallAppleEventHandler( const AEEventClass pClass, const AEEventID pID )
  696. {
  697.     // installs the AppleEvent hook for the given apple event
  698.     
  699.     if ( gMacInfo.hasAppleEvents )
  700.         FailOSErr( AEInstallEventHandler( pClass, pID, gAEUPP, (long) gApplication, FALSE ));
  701. }
  702.  
  703.  
  704. #pragma mark -
  705. /*---------------------------------*********************---------------------------------*/
  706.  
  707.  
  708. static pascal OSErr            ZAEHandler( AppleEvent* aeEvt, AppleEvent* reply, long refCon )
  709. {
  710.     // this is the global vector proc that is called for every apple evnt. This determines the
  711.     // event class and ID, then sends that info, plus the event, up the command chain, where,
  712.     // presumably, it will be handled.
  713.  
  714.     AEEventClass    pClass;
  715.     AEEventID        pID;
  716.     DescType        returnedType;
  717.     long            returnedSize;
  718.     OSErr            theErr = noErr;
  719.     
  720.     try
  721.     {
  722.         // determine the AE class and ID (this is laborious, so it's done here once and passed on)
  723.     
  724.         FailOSErr( AEGetAttributePtr(     aeEvt, keyEventClassAttr,
  725.                                          typeType, &returnedType,
  726.                                          &pClass, sizeof( AEEventClass ), &returnedSize ));
  727.  
  728.         FailOSErr( AEGetAttributePtr(     aeEvt, keyEventIDAttr,
  729.                                          typeType, &returnedType,
  730.                                          &pID, sizeof( AEEventID ), &returnedSize ));
  731.  
  732.         // send the event up the command chain
  733.     
  734.         if ( gCurHandler )
  735.             gCurHandler->HandleAppleEvent( pClass, pID, aeEvt, reply );
  736.         else
  737.             theErr = errAEEventNotHandled;
  738.     }
  739.     catch( OSErr err )
  740.     {
  741.         theErr = err;
  742.         
  743.         // exceptions are not propagated, but returned to applescript as
  744.         // an error code
  745.     }    
  746.     
  747.     return theErr;
  748. }            
  749.  
  750.